import { IToken } from '../lexer/token';

/**
 * 词法Tokens扫描器
 *
 * @export
 * @class Scanner
 */
export class Scanner {
  private tokens: IToken[] = [];

  private index = 0;

  constructor(tokens: IToken[], index = 0) {
    // ignore whitespace, comment
    // 忽略空格、注释。克隆tokens
    this.tokens = tokens.slice();
    this.index = index;
  }

  /**
   * 读取当前token
   * @use index
   * @memberof Scanner
   */
  public read = () => {
    const token = this.tokens[this.index];
    if (token) {
      return token;
    }
    return false;
  };

  /**
   * index +1
   * @memberof Scanner
   */
  public next = () => {
    this.index += 1;
  };

  public isEnd = () => {
    return this.index >= this.tokens.length;
  };

  public getIndex = () => {
    return this.index;
  };

  public setIndex = (index: number) => {
    this.index = index;
    return index;
  };

  /**
   * tokens剩余数量
   * @memberof Scanner
   */
  public getRestTokenCount = () => {
    return this.tokens.length - this.index - 1;
  };

  /**
   * 获取下一个token
   * @param {IToken} token
   * @memberof Scanner
   */
  public getNextByToken = (token: IToken) => {
    const currentTokenIndex = this.tokens.findIndex(eachToken => {
      return eachToken === token;
    });
    if (currentTokenIndex > -1) {
      if (currentTokenIndex + 1 < this.tokens.length) {
        return this.tokens[currentTokenIndex + 1];
      }
      return null;
    }
    throw Error(`token ${token.value.toString()} not exist in scanner.`);
  };

  /**
   * 根据position获取token
   * 如：s|elect、select|，获取select
   * @param {number} characterIndex
   * @memberof Scanner
   */
  public getTokenByCharacterIndex = (characterIndex: number) => {
    if (characterIndex === null) {
      return null;
    }

    for (const token of this.tokens) {
      // position[0]<= charcterIndex <= position[1]+1
      if (characterIndex >= token.position[0] && characterIndex - 1 <= token.position[1]) {
        return token;
      }
    }

    return null;
  };

  /**
   * 根据position获取上一个token
   *
   * @param {number} characterIndex
   * @memberof Scanner
   */
  public getPrevTokenByCharacterIndex = (characterIndex: number) => {
    let prevToken: IToken = null;
    let prevTokenIndex: number = null;

    this.tokens.forEach((token, index) => {
      if (token.position[1] < characterIndex - 1) {
        prevToken = token;
        prevTokenIndex = index;
      }
    });

    return { prevToken, prevTokenIndex };
  };

  /**
   * 根据position获取下一个token
   *
   * @param {number} characterIndex
   * @memberof Scanner
   */
  public getNextTokenFromCharacterIndex = (characterIndex: number) => {
    for (const token of this.tokens) {
      if (token.position[0] > characterIndex) {
        return token;
      }
    }

    return null;
  };

  /**
   * 添加词法token
   *
   * @param {IToken} token
   * @memberof Scanner
   */
  public addToken = (token: IToken) => {
    const { prevToken, prevTokenIndex } = this.getPrevTokenByCharacterIndex(token.position[0]);
    // 这时tokens中的其他token.position不准
    // 除非token.value为null或''
    if (prevToken) {
      // prevTokenIndex
      // 添加到数组
      this.tokens.splice(prevTokenIndex + 1, 0, token);
    } else {
      // 数组开头添加
      this.tokens.unshift(token);
    }
  };
}
